<?php

class Util
{
    static function json_encode($input){
        // 从 PHP 5.4.0 起, 增加了这个选项.
        if(defined('JSON_UNESCAPED_UNICODE')){
            return json_encode($input, JSON_UNESCAPED_UNICODE);
        }
        if(is_string($input)){
            $text = $input;
            $text = str_replace('\\', '\\\\', $text);
            $text = str_replace(
                array("\r", "\n", "\t", "\""),
                array('\r', '\n', '\t', '\\"'),
                $text);
            return '"' . $text . '"';
        }else if(is_array($input) || is_object($input)){
            $arr = array();
            $is_obj = is_object($input) || (array_keys($input) !== range(0, count($input) - 1));
            foreach($input as $k=>$v){
                if($is_obj){
                    $arr[] = self::json_encode($k) . ':' . self::json_encode($v);
                }else{
                    $arr[] = self::json_encode($v);
                }
            }
            if($is_obj){
                return '{' . join(',', $arr) . '}';
            }else{
                return '[' . join(',', $arr) . ']';
            }
        }else{
            return $input . '';
        }
    }
}


class WeChat{

	var $member_id;
	var $config;

	var $_config;

	function __construct($member_id){
		$this->member_id = $member_id;
		$this->_config = $config = Model('wechat_config')->where(array('member_id' => $this->member_id))->find();
		unset($this->_config['id']);
		$this->config = json_decode($config['config'],true);

	}

	function get_config(){
		return $this->config;
	}

	private function get_access_token(){
		//优先查找数据库
		$time = time();
		//清理过期数据
		Model('wechat_access_token')->where(array('expires_time' => array('lt',$time)))->delete();

		$accesstoken = Model('wechat_access_token')->where(array('member_id' => $this->member_id, 'expires_time' => array('gt',$time)))->find();

		if(count($accesstoken)){
			return $accesstoken['access_token'];
		}
		else{
			//请求新接口
			$url = 'https://api.weixin.qq.com/cgi-bin/token?';
			$param = array(
				'grant_type' => 'client_credential',
				'appid' => $this->config['appid'],
				'secret' => $this->config['appsecret']
			);
			$url .= http_build_query($param);

			$result = json_decode(file_get_contents($url),true);

			if(isset($result['errcode'])){
				return '';
			}
			else{
				Model('wechat_access_token')->insert(array(
					'access_token' => $result['access_token'],
					//因为可能存延时，保险起见，将时间削去600秒
					'expires_time' => $time + $result['expires_in'] - 600,

					'member_id' => $this->member_id
				));
				return $result['access_token'];
			}
		}


	}

	public function get_jsapi_ticket(){
		$time = time();
		@$ticket = file_get_contents('ticket.data');
		if(!empty($ticket)){
			$json = json_decode($ticket,true);
			if($time < $json['expr_time']){
				return $json['ticket'];
			}
		}
		$access_token = $this->get_access_token();
		$url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$access_token.'&type=jsapi';
		$result = file_get_contents($url);
		$json = json_decode($result,true);
		if($json['errcode'] == 0){
			//cache ticket
			$cache = array(
				'ticket' => $json['ticket'],
				'expr_time' => $time + $json['expires_in'] - 600
			);
			@file_put_contents('ticket.data',json_encode($cache));
			return $json['ticket'];
		}

		return false;
	}

	public function get_sign_access_token($code){
		$time = time();
		// $access_token = Model('wechat_another_access_token')->where(array('expr_time' => array('gt',$time)))->find();
		// if($access_token && count($access_token)){
		// 	return $access_token['access_token'];
		// }

		$url = "https://api.weixin.qq.com/sns/oauth2/access_token?";

		$param = array(
			'appid' => $this->config['appid'],
			'secret' => $this->config['appsecret'],
			'code' => $code,
			'grant_type' => 'authorization_code'
		);
		$url .= http_build_query($param);

		$result = $this->post($url);


		$json = json_decode($result,true);

		if($json['access_token']){
			//cache it
			Model('wechat_another_access_token')->insert(array(
				'access_token' => $json['access_token'],
				'expr_time' => $time + $json['expires_in']
			));

			return array($json['access_token'],$json['openid']);
		}

		return array();

	}


	function get_user_info($openid){
		$access_token = $this->get_access_token();
		$url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=$access_token&openid=$openid&lang=zh_CN";
		$result = $this->post($url);
		$json = json_decode($result,true);
		return $json;
	}

	private function update($data){
		foreach($data as $key => $val){
			$this->_config[$key] = $val;
		}
		Model('wechat_config')->insert($this->_config,true);
	}


	public function get_menu_list(){
		// echo $access_token = $this->get_access_token();

		//优先从数据库中获得
		if(!empty($this->_config['custom_menu'])){
			return json_decode($this->_config['custom_menu'],true);
		}

		$access_token = $this->get_access_token();
		$url = 'https://api.weixin.qq.com/cgi-bin/menu/get?access_token=' . $access_token;
		$result = file_get_contents($url); 

		$json = json_decode($result,true);

		//如果为空存进数据库
		if(empty($this->_config['custom_menu'])){
			//如果没有错误
			if(!isset($json['errcode'])){
				$this->update(array(
					'custom_menu' => $result
				));
			}
		}
		if(isset($json['errcode'])){
			return array('menu' => array());
		}
		else{
			return $json;
		}

		// return json_decode($result,true);
	}

	public function set_menu_list($json){
		//php5.4以前不能转义
		// $json = Util::json_encode($json);
		$access_token = $this->get_access_token();
		//先删除之前的菜单
		$url = 'https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=' . $access_token;

		@file_get_contents($url);

		$json = htmlspecialchars_decode($json);

		//更新菜单
		$url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' . $access_token;

		$result = $this->post($url,$json);

		$result = json_decode($result,true);


		if($result['errcode'] == 0){
			$this->update(array('custom_menu' => ''));
			exit('success');
		}
		else{
			exit('failed');
		}
	}

	public function get_answer_list(){
		// $access_token = 
		return empty($this->_config['reply']) ? array() : $this->_config['reply'];
	}

	static function get_reply_list($source_id){

		$list = Model('wechat_config')->where(array('source_id' => trim($source_id)))->find();
		return empty($list['reply']) ? array() : $list['reply'];

	}


	static function response($obj){
		$answer_list = self::get_reply_list($obj->ToUserName);
		$answer_list = json_decode($answer_list,true);
		foreach($answer_list as $key => $val){
			$kw = $val['key_word'];
			if(strpos(trim($obj->Content),$kw) !== false){
				$reply = $val['reply'];
				$type = $val['type'];
				$time = time();
				echo "<xml>
				<ToUserName><![CDATA[{$obj->FromUserName}]]></ToUserName>
				<FromUserName><![CDATA[{$obj->ToUserName}]]></FromUserName>
				<CreateTime>{$time}</CreateTime>
				<MsgType><![CDATA[{$type}]]></MsgType>
				<Content><![CDATA[{$reply}]]></Content>
				</xml>";
				exit;
			}
		}

		

		exit;
	}



	private function post($url,$data = null){
	    $curl = curl_init();
	    curl_setopt($curl, CURLOPT_URL, $url);
	    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
	    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
	    if (!empty($data)){
	        curl_setopt($curl, CURLOPT_POST, 1);
	        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
	    }
	    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
	    $output = curl_exec($curl);
	    curl_close($curl);
	    return $output;
	}




}

class wechatCallbackapiTest
{
	public function valid()
    {
        $echoStr = $_GET["echostr"];

        //valid signature , option
        if($this->checkSignature()){
        	echo $echoStr;
        	exit;
        }
    }

    public function responseMsg()
    {
		//get post data, May be due to the different environments
		$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];

      	//extract post data
		if (!empty($postStr)){
                /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
                   the best way is to check the validity of xml by yourself */
                libxml_disable_entity_loader(true);
              	$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
                $fromUsername = $postObj->FromUserName;
                $toUsername = $postObj->ToUserName;
                $keyword = trim($postObj->Content);
                $time = time();
                $textTpl = "<xml>
							<ToUserName><![CDATA[%s]]></ToUserName>
							<FromUserName><![CDATA[%s]]></FromUserName>
							<CreateTime>%s</CreateTime>
							<MsgType><![CDATA[%s]]></MsgType>
							<Content><![CDATA[%s]]></Content>
							<FuncFlag>0</FuncFlag>
							</xml>";             
				if(!empty( $keyword ))
                {
              		$msgType = "text";
                	$contentStr = "Welcome to wechat world!";
                	$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
                	echo $resultStr;
                }else{
                	echo "Input something...";
                }

        }else {
        	echo "";
        	exit;
        }
    }
		
	private function checkSignature()
	{
        // you must define TOKEN by yourself
        if (!defined("TOKEN")) {
            throw new Exception('TOKEN is not defined!');
        }


        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];
        		
		$token = TOKEN;
		$tmpArr = array($token, $timestamp, $nonce);
        // use SORT_STRING rule
		sort($tmpArr, SORT_STRING);
		$tmpStr = implode( $tmpArr );
		$tmpStr = sha1( $tmpStr );
		
		if( $tmpStr == $signature ){
			return true;
		}else{
			return false;
		}
	}
}


?>